﻿using System;
using RingBuffer;

namespace kratos {

/// <summary>
/// 对象序列化/反序列化接口
/// </summary>
public abstract class Serializer {
  public abstract byte[] serialize(Object obj);
  public abstract Object deserialize(byte[] data, int size);
}

/// <summary>
/// 字节流加密解密接口
/// </summary>
public abstract class Encryptor {
  public abstract byte[] encrypt(byte[] data, int size);
  public abstract byte[] decrypt(byte[] data, int size);
}

/// <summary>
/// 客户端事件处理器
/// </summary>
public abstract class IClientHandler {
  /// <summary>
  /// 当连接建立完成时触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  public abstract void OnConnect(IClient client);
  /// <summary>
  /// 重连完成时触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  public abstract void OnReconnect(IClient client);
  /// <summary>
  /// 当连接失败时触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  public abstract void OnConnectFail(IClient client);
  /// <summary>
  /// 当连接关闭时触发，无论时对端主动关闭，还是主动关闭都会触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  public abstract void OnClose(IClient client);
  /// <summary>
  /// 当对端有数据流发送过来时触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  /// <param name="rb">读缓冲区</param>
  public abstract void OnReceive(IClient client, GrowingRingBuffer<byte> rb);
  /// <summary>
  /// 在读超时的时间段内没有触发过任何读事件时触发，用于心跳包发送
  /// </summary>
  /// <param name="client">客户端实例</param>
  public abstract void OnReceiveTimeout(IClient client);
  /// <summary>
  /// 当这设置对象序列化器时，对端有数据到来时触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  /// <param name="obj">调用用户提供的序列化器反序列化出来的对象实例</param>
  public abstract void OnReceiveObject(IClient client, Object obj);
  /// <summary>
  /// 当发送失败时触发
  /// </summary>
  /// <param name="client">客户端实例</param>
  public abstract void OnSendFail(IClient client);
  public static implicit operator bool(IClientHandler handler) {
    return (handler != null);
  }
}

/// <summary>
/// TCP客户端接口
/// </summary>
public interface IClient : IDisposable {
  /// <summary>
  /// 连接远程主机
  /// </summary>
  /// <param name="host">主机地址</param>
  /// <param name="port">主机端口</param>
  /// <param name="timeout">连接超时，毫秒</param>
  /// <param
  /// name="recv_timeout">读超时，毫秒，在recv_timeout时间内没有接收到任何网络数据则触发读超时事件</param>
  /// <param name="handler">网络事件处理器</param>
  /// <returns></returns>
  bool Connect(string host, int port, long timeout, long recv_timeout,
               IClientHandler handler);
  bool Connect(string host, int port, IClientHandler handler);
  /// <summary>
  /// 对象序列化/反序列化处理器
  /// </summary>
  Serializer ObjectSerializer {
    get;
    set;
  }
  /// <summary>
  /// 加密/解密处理器
  /// </summary>
  Encryptor Cryptor {
    get;
    set;
  }
  /// <summary>
  /// 重连
  /// </summary>
  /// <returns>true或false</returns>
  bool Reconnect();
  /// <summary>
  /// 是否已经连接完成
  /// </summary>
  bool Connected { get; }
  /// <summary>
  /// 主动关闭连接
  /// </summary>
  void Close();
  /// <summary>
  /// 逻辑主循环，在框架主循环内调用
  /// </summary>
  void Update();
  /// <summary>
  /// 发送数据
  /// </summary>
  /// <param name="data">数据块</param>
  /// <param name="size">数据长度，字节</param>
  /// <returns>已发送的字节数</returns>
  int Send(byte[] data, int size);
  /// <summary>
  /// 发送对象，需要设置Serializer
  /// </summary>
  /// <param name="obj">对象</param>
  /// <returns>true或false</returns>
  bool Send(Object obj);
}

/// <summary>
/// 客户端工厂
/// </summary>
public class ClientFactory {
  /// <summary>
  /// 建立一个客户端实例
  /// </summary>
  /// <returns>客户端实例</returns>
  public static IClient Create() { return new Client(); }
}

}
